package arithmetic.socket.netty.chat;


import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;

/**
 * 自定义 http处理器
 * Created on 2020-01-20
 */
@Slf4j
public class ChatServerHandler extends SimpleChannelInboundHandler<String> {

    // 静态list存储所有链接 // GlobalEventExecutor.INSTANCE单线程执行实例,
    static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    /**
     * 读取客服端请求,并且响应的处理方法
     * 做转发操作!
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        System.out.println("out:"+msg);
        Channel channel = ctx.channel();
        channelGroup.forEach(ch->{
            if (ch != channel) {
                ch.writeAndFlush("[" + channel.remoteAddress() + "]:" + msg);
            }else {
                ch.writeAndFlush("[自己]:" + msg);
            }
        });
    }


    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        // 遍历了每个 channel
        channelGroup.writeAndFlush("[系统]:"+channel.remoteAddress()+"加入");
        channelGroup.add(channel);
        super.handlerAdded(ctx);
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        channelGroup.writeAndFlush("[系统]:"+channel.remoteAddress()+"离开");
        // 不需要 remove,下线了容器自动剔除掉
        super.handlerRemoved(ctx);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        //广播上线
        channelGroup.writeAndFlush("[系统]:"+channel.remoteAddress()+"上线");
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        channelGroup.writeAndFlush("[系统]:"+ctx.channel().remoteAddress()+"下线");
        super.channelInactive(ctx);
    }

    /**
     * 捕获异常
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        super.exceptionCaught(ctx, cause);
    }
}
